#include "../Source/server.hpp"
#include <fstream>
#include <sys/stat.h>

std::unordered_map<int, std::string> _StatuDescribe = {
    {100, "Continue"},
    {101, "Switching Protocol"},
    {102, "Processing"},
    {103, "Early Hints"},
    {200, "OK"},
    {201, "Created"},
    {202, "Accepted"},
    {203, "Non-Authoritative Information"},
    {204, "No Content"},
    {205, "Reset Content"},
    {206, "Partial Content"},
    {207, "Multi-Status"},
    {208, "Already Reported"},
    {226, "IM Used"},
    {300, "Multiple Choice"},
    {301, "Moved Permanently"},
    {302, "Found"},
    {303, "See Other"},
    {304, "Not Modified"},
    {305, "Use Proxy"},
    {306, "unused"},
    {307, "Temporary Redirect"},
    {308, "Permanent Redirect"},
    {400, "Bad Request"},
    {401, "Unauthorized"},
    {402, "Payment Required"},
    {403, "Forbidden"},
    {404, "Not Found"},
    {405, "Method Not Allowed"},
    {406, "Not Acceptable"},
    {407, "Proxy Authentication Required"},
    {408, "Request Timeout"},
    {409, "Conflict"},
    {410, "Gone"},
    {411, "Length Required"},
    {412, "Precondition Failed"},
    {413, "Payload Too Large"},
    {414, "URI Too Long"},
    {415, "Unsupported Media Type"},
    {416, "Range Not Satisfiable"},
    {417, "Expectation Failed"},
    {418, "I'm a teapot"},
    {421, "Misdirected Request"},
    {422, "Unprocessable Entity"},
    {423, "Locked"},
    {424, "Failed Dependency"},
    {425, "Too Early"},
    {426, "Upgrade Required"},
    {428, "Precondition Required"},
    {429, "Too Many Requests"},
    {431, "Request Header Fields Too Large"},
    {451, "Unavailable For Legal Reasons"},
    {501, "Not Implemented"},
    {502, "Bad Gateway"},
    {503, "Service Unavailable"},
    {504, "Gateway Timeout"},
    {505, "HTTP Version Not Supported"},
    {506, "Variant Also Negotiates"},
    {507, "Insufficient Storage"},
    {508, "Loop Detected"},
    {510, "Not Extended"},
    {511, "Network Authentication Required"}};

std::unordered_map<std::string, std::string> _mine = {
    {".aac", "audio/aac"},
    {".abw", "application/x-abiword"},
    {".arc", "application/x-freearc"},
    {".avi", "video/x-msvideo"},
    {".azw", "application/vnd.amazon.ebook"},
    {".bin", "application/octet-stream"},
    {".bmp", "image/bmp"},
    {".bz", "application/x-bzip"},
    {".bz2", "application/x-bzip2"},
    {".csh", "application/x-csh"},
    {".css", "text/css"},
    {".csv", "text/csv"},
    {".doc", "application/msword"},
    {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
    {".eot", "application/vnd.ms-fontobject"},
    {".epub", "application/epub+zip"},
    {".gif", "image/gif"},
    {".htm", "text/html"},
    {".html", "text/html"},
    {".ico", "image/vnd.microsoft.icon"},
    {".ics", "text/calendar"},
    {".jar", "application/java-archive"},
    {".jpeg", "image/jpeg"},
    {".jpg", "image/jpeg"},
    {".js", "text/javascript"},
    {".json", "application/json"},
    {".jsonld", "application/ld+json"},
    {".mid", "audio/midi"},
    {".midi", "audio/x-midi"},
    {".mjs", "text/javascript"},
    {".mp3", "audio/mpeg"},
    {".mpeg", "video/mpeg"},
    {".mpkg", "application/vnd.apple.installer+xml"},
    {".odp", "application/vnd.oasis.opendocument.presentation"},
    {".ods", "application/vnd.oasis.opendocument.spreadsheet"},
    {".odt", "application/vnd.oasis.opendocument.text"},
    {".oga", "audio/ogg"},
    {".ogv", "video/ogg"},
    {".ogx", "application/ogg"},
    {".otf", "font/otf"},
    {".png", "image/png"},
    {".pdf", "application/pdf"},
    {".ppt", "application/vnd.ms-powerpoint"},
    {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
    {".rar", "application/x-rar-compressed"},
    {".rtf", "application/rtf"},
    {".sh", "application/x-sh"},
    {".svg", "image/svg+xml"},
    {".swf", "application/x-shockwave-flash"},
    {".tar", "application/x-tar"},
    {".tif", "image/tiff"},
    {".tiff", "image/tiff"},
    {".ttf", "font/ttf"},
    {".txt", "text/plain"},
    {".vsd", "application/vnd.visio"},
    {".wav", "audio/wav"},
    {".weba", "audio/webm"},
    {".webm", "video/webm"},
    {".webp", "image/webp"},
    {".woff", "font/woff"},
    {".woff2", "font/woff2"},
    {".xhtml", "application/xhtml+xml"},
    {".xls", "application/vnd.ms-excel"},
    {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
    {".xml", "application/xml"},
    {".xul", "application/vnd.mozilla.xul+xml"},
    {".zip", "application/zip"},
    {".3gp", "video/3gpp"},
    {".3g2", "video/3gpp2"},
    {".7z", "application/x-7z-compressed"}};

class Util
{
public:
    // 字符串分割函数,以sep为分割符分割src,结果全部放到_Vstring中
    static size_t Split(const std::string &src, const std::string &sep, std::vector<std::string> *_Vstring)
    {
        int offest = 0;
        while (offest < src.size())
        {
            size_t pos = src.find(sep, offest);
            if (pos == std::string::npos)
            {
                _Vstring->push_back(src.substr(offest));
                return _Vstring->size();
            }
            if (pos == offest)
            {
                offest = pos + sep.size();
                continue;
            }
            _Vstring->push_back(src.substr(offest, pos - offest));
            offest = pos + sep.size();
        }

        return _Vstring->size();
    }
    static bool ReadFile(const std::string &filename, std::string *buf) // 读取文件内容
    {
        std::ifstream ifs(filename, std::ios::binary);
        if (ifs.is_open() == false)
        {
            printf("OPEN %s FILE FAILED!!", filename.c_str());
            return false;
        }
        size_t fsize = 0;
        ifs.seekg(0, ifs.end); // 跳转读写位置到末尾
        fsize = ifs.tellg();   // 获取当前读写位置相对于起始位置的偏移量，从末尾偏移刚好就是文件大小
        ifs.seekg(0, ifs.beg); // 跳转到起始位置
        buf->resize(fsize);    // 开辟文件大小的空间
        ifs.read(&(*buf)[0], fsize);
        if (ifs.good() == false)
        {
            printf("READ %s FILE FAILED!!", filename.c_str());
            ifs.close();
            return false;
        }
        ifs.close();
        return true;
    }
    static bool WriteFile(const std::string &filename, const std::string &buf) // 向文件写入内容
    {
        std::ofstream ofs(filename, std::ios::binary | std::ios::trunc);
        if (ofs.is_open() == false)
        {
            printf("OPEN %s FILE FAILED!!", filename.c_str());
            return false;
        }
        ofs.write(buf.c_str(), buf.size());
        if (ofs.good() == false)
        {
            LOG_ERROR("WRITE %s FILE FAILED!", filename.c_str());
            ofs.close();
            return false;
        }
        ofs.close();
        return true;
    }

    static std::string UrlEncode(const std::string url, bool convert_space_to_plus) // url编码
    {
        std::string res;
        for (auto &c : url)
        {
            if (c == '.' || c == '-' || c == '_' || c == '~' || isalnum(c))
            {
                res += c;
                continue;
            }
            if (c == ' ' && convert_space_to_plus == true)
            {
                res += '+';
                continue;
            }
            // 剩下的字符都是需要编码成为 %HH 格式
            char tmp[4] = {0};
            // snprintf 与 printf比较类似，都是格式化字符串，只不过一个是打印，一个是放到一块空间中
            snprintf(tmp, 4, "%%%02X", c);
            res += tmp;
        }
        return res;
    }

    static char HEXTOI(char c)
    {
        if (c >= '0' && c <= '9')
        {
            return c - '0';
        }
        else if (c >= 'a' && c <= 'z')
        {
            return c - 'a' + 10;
        }
        else if (c >= 'A' && c <= 'Z')
        {
            return c - 'A' + 10;
        }
        return -1;
    }

    static std::string UrlDecode(const std::string url, bool convert_plus_to_space) // url解码
    {
        // 遇到了%，则将紧随其后的2个字符，转换为数字，第一个数字左移4位，然后加上第二个数字  + -> 2b  %2b->2 << 4 + 11
        std::string res;
        for (int i = 0; i < url.size(); i++)
        {
            if (url[i] == '+' && convert_plus_to_space == true)
            {
                res += ' ';
                continue;
            }
            if (url[i] == '%' && (i + 2) < url.size())
            {
                char v1 = HEXTOI(url[i + 1]);
                char v2 = HEXTOI(url[i + 2]);
                char v = v1 * 16 + v2;
                res += v;
                i += 2;
                continue;
            }
            res += url[i];
        }
        return res;
    }

    static std::string StatuDescribe(int _status_code) // 响应状态码描述
    {
        auto it = _StatuDescribe.find(_status_code);
        if (it != _StatuDescribe.end())
        {
            return it->second;
        }
        return "UnKnown";
    }

    static std::string ExMime(const std::string &filename) // 根据文件后缀获取文件mime
    {
        auto pos = filename.rfind(".");
        if (pos == std::string::npos)
        {
            return "application-octet-stream";
        }

        std::string _Suffix = filename.substr(pos);
        auto it = _mine.find(_Suffix);
        if (it != _mine.end())
        {
            return it->second;
        }
        return "application-octet-stream";
    }

    static bool IsDirectory(const std::string &filename)
    {
        struct stat st;
        int ret = stat(filename.c_str(), &st);
        if (ret < 0)
        {
            return false;
        }
        return S_ISDIR(st.st_mode);
    }
    // 判断一个文件是否是一个普通文件
    static bool IsRegular(const std::string &filename)
    {
        struct stat st;
        int ret = stat(filename.c_str(), &st);
        if (ret < 0)
        {
            return false;
        }
        return S_ISREG(st.st_mode);
    }
    static bool IsValid(const std::string &path) // 判断http请求资源路径是否有效
    {
        std::vector<std::string> _Vstring;
        Split(path, "/", &_Vstring);
        int level = 0;
        for (auto &dir : _Vstring)
        {
            if (dir == "..")
            {
                level--;
                if (level < 0)
                {
                    return false;
                }
                continue;
            }

            level++;
        }
        return true;
    }
};

class HttpRequest
{
public:
    HttpRequest():_version("HTTP/1.1")
    {}
    void Reset()
    {
        _method.clear();
        _path.clear();
        _version = "HTTP/1.1";
        _body.clear();
        _header.clear();
        _parament.clear();
        std::smatch match;
        _match.swap(match);
    }

    void SetHeader(const std::string &_key, const std::string &_value) // 设置头部KEY:VALUE字段
    {
        _header[_key] = _value;
    }

    bool HasHeader(const std::string &_key) // 判断是否有指定的头部字段
    {
        auto it = _header.find(_key);
        if (it == _header.end())
        {
            return false;
        }
        return true;
    }

    std::string GetHeaderValue(const std::string &_key) // 获取指定头部字段的值
    {
        if (HasHeader(_key))
        {
            return _header[_key];
        }
        return "UnKnown";
    }

    void SetParament(const std::string &_key, const std::string &_value) // 设置参数
    {
        _parament[_key] = _value;
    }

    bool HasParament(const std::string &_key) // 获取指定参数
    {
        auto it = _parament.find(_key);
        if (it == _parament.end())
        {
            return false;
        }
        return true;
    }

    std::string GetParaValue(const std::string &_key) // 获取指定参数的值
    {
        if (HasParament(_key))
        {
            return _parament[_key];
        }
        return "UnKnown";
    }

    size_t GetContentLength()
    {
        std::string _value = GetHeaderValue("Content-Length");
        return _value == "UnKnown" ? 0 : std::stol(_value);
    }

    bool Close() // 判断是否为短链接
    {
        if (HasHeader("Connection") && GetHeaderValue("Connection") == "keep-alive")
        {
            return false;
        }
        return true;
    }

public:
    std::string _method;                                    // 请求方法
    std::string _path;                                      // 资源路径
    std::string _version;                                   // 协议版本
    std::string _body;                                      // 请求正文
    std::unordered_map<std::string, std::string> _header;   // 请求头部字段 KEY:VALUE
    std::unordered_map<std::string, std::string> _parament; // 参数
    std::smatch _match;                                     // url中的正则提取数据
};

class HttpResponse
{
public:
    int _status;                                           // 状态码
    bool _redict_flag;                                     // 重定向标志
    std::string _body;                                     // 响应正文
    std::string _redict_url;                               // 重定向之后的路径
    std::unordered_map<std::string, std::string> _headers; // 响应头部数据
public:
    HttpResponse() : _status(200), _redict_flag(false)
    {
    }

    HttpResponse(int status) : _status(status), _redict_flag(false)
    {
    }

    void Reset()
    {
        _status = 200;
        _redict_flag = false;
        _body.clear();
        _redict_url.clear();
        _headers.clear();
    }
    void SetHeader(const std::string &_key, const std::string &_value) // 设置头部KEY:VALUE字段
    {
        _headers[_key] = _value;
    }

    bool HasHeader(const std::string &_key) // 判断是否有指定的头部字段
    {
        auto it = _headers.find(_key);
        if (it == _headers.end())
        {
            return false;
        }
        return true;
    }

    std::string GetHeaderValue(const std::string &_key) // 获取指定头部字段的值
    {
        if (HasHeader(_key))
        {
            return _headers[_key];
        }
        return "UnKnown";
    }
    void SetRedict(const std::string &_redict, int status = 302)
    {
        _redict_url = _redict;
        _redict_flag = true;
        _status = status;
    }

    void SetContent(const std::string &body, const std::string type = "text/html") // 设置响应正文
    {
        _body = body;
        SetHeader("Content-Type", type);
    }

    bool Close()
    {
        if (HasHeader("Connection") && _headers["Connection"] == "keep-alive")
        {
            return false;
        }
        return true;
    }
};

typedef enum
{
    HTTP_RECV_ERROR,
    HTTP_RECV_LINE,
    HTTP_RECV_HEAD,
    HTTP_RECV_BODY,
    HTTP_RECV_OVER
} HttpRecvStatus;

#define MAX_SIZE 8192

class HttpContext
{
private:
    int _resp_status;            // 响应状态码
    HttpRecvStatus _recv_status; // 当前接收并解析的状态
    HttpRequest _req_message;    // 当前已经处理的请求信息

private:
    bool RecvHttpLine(Buffer *_buf)
    {
        std::string _line = _buf->GetLine();
        if (_line.empty())
        {
            if (_buf->ReadbleSize() > MAX_SIZE)
            {
                _resp_status = 414;
                _recv_status = HTTP_RECV_ERROR;
                return false;
            }

            return true;
        }

        if (_line.size() > MAX_SIZE)
        {

            _resp_status = 414;
            _recv_status = HTTP_RECV_ERROR;
            return false;
        }
        bool ret = PraseHttpLine(_line);
        if (!ret)
        {
            return false;
        }
        _buf->MoveReadOffest(_line.size());
        _recv_status = HTTP_RECV_HEAD;
        return true;
    }

    bool PraseHttpLine(const std::string &line)
    {
        std::smatch matches;
        std::regex e("(GET|HEAD|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?", std::regex::icase);
        bool ret = std::regex_match(line, matches, e);
        if (ret == false)
        {
            _recv_status = HTTP_RECV_ERROR;
            _resp_status = 400; // BAD REQUEST
            return false;
        }
        // 0 : GET /wyc/login?user=wyc&pass=15586880866 HTTP/1.1
        // 1 : GET
        // 2 : /wyc/login
        // 3 : user=wyc&pass=15586880866
        // 4 : HTTP/1.1
        // 请求方法的获取
        _req_message._method = matches[1];
        // 资源路径的获取，需要进行URL解码操作，但是不需要+转空格
        std::transform(_req_message._method.begin(),
                       _req_message._method.end(), _req_message._method.begin(), ::toupper);
        _req_message._path = Util::UrlDecode(matches[2], false);
        // 协议版本的获取
        _req_message._version = matches[4];
        // 查询字符串的获取与处理
        std::vector<std::string> query_string_arry;
        std::string query_string = matches[3];
        // 查询字符串的格式 key=val&key=val....., 先以 & 符号进行分割，得到各个字串
        Util::Split(query_string, "&", &query_string_arry);
        // 针对各个字串，以 = 符号进行分割，得到key 和val， 得到之后也需要进行URL解码
        for (auto &str : query_string_arry)
        {
            size_t pos = str.find("=");
            if (pos == std::string::npos)
            {
                _recv_status = HTTP_RECV_ERROR;
                _resp_status = 400; // BAD REQUEST
                return false;
            }
            std::string key = Util::UrlDecode(str.substr(0, pos), true);
            std::string val = Util::UrlDecode(str.substr(pos + 1), true);
            _req_message.SetParament(key, val);
        }
        return true;
    }
    bool RecvHttpHead(Buffer *buf)
    {
        if (_recv_status != HTTP_RECV_HEAD)
            return false;
        // 一行一行取出数据，直到遇到空行为止， 头部的格式 key: val\r\nkey: val\r\n....
        while (1)
        {
            std::string line = buf->GetLineAndPop();
            // 2. 需要考虑的一些要素：缓冲区中的数据不足一行， 获取的一行数据超大
            if (line.size() == 0)
            {
                // 缓冲区中的数据不足一行，则需要判断缓冲区的可读数据长度，如果很长了都不足一行，这是有问题的
                if (buf->ReadbleSize() > MAX_SIZE)
                {
                    _recv_status = HTTP_RECV_ERROR;
                    _resp_status = 414; // URI TOO LONG
                    return false;
                }
                // 缓冲区中数据不足一行，但是也不多，就等等新数据的到来
                return true;
            }
            if (line.size() > MAX_SIZE)
            {
                _recv_status = HTTP_RECV_ERROR;
                _resp_status = 414; // URI TOO LONG
                return false;
            }
            if (line == "\n" || line == "\r\n")
            {
                break;
            }
            bool ret = PraseHttpHead(line);
            if (ret == false)
            {
                return false;
            }
        }
        // 头部处理完毕，进入正文获取阶段
        _recv_status = HTTP_RECV_BODY;
        return true;
    }
    bool PraseHttpHead(std::string &line)
    {
        // key: val\r\nkey: val\r\n....
        if (line.back() == '\n')
            line.pop_back(); // 末尾是换行则去掉换行字符
        if (line.back() == '\r')
            line.pop_back(); // 末尾是回车则去掉回车字符
        size_t pos = line.find(": ");
        if (pos == std::string::npos)
        {
            _recv_status = HTTP_RECV_ERROR;
            _resp_status = 400; //
            return false;
        }
        std::string key = line.substr(0, pos);
        std::string val = line.substr(pos + 2);
        _req_message.SetHeader(key, val);
        return true;
    }
    bool RecvHttpBody(Buffer *buf)
    {
        if (_recv_status != HTTP_RECV_BODY)
            return false;
        // 1. 获取正文长度
        size_t content_length = _req_message.GetContentLength();
        if (content_length == 0)
        {
            // 没有正文，则请求接收解析完毕
            _recv_status = HTTP_RECV_OVER;
            return true;
        }
        // 2. 当前已经接收了多少正文,其实就是往  _request._body 中放了多少数据了
        size_t real_len = content_length - _req_message._body.size(); // 实际还需要接收的正文长度
        // 3. 接收正文放到body中，但是也要考虑当前缓冲区中的数据，是否是全部的正文
        //   3.1 缓冲区中数据，包含了当前请求的所有正文，则取出所需的数据
        if (buf->ReadbleSize() >= real_len)
        {
            _req_message._body.append(buf->ReadPosition(), real_len);
            buf->MoveReadOffest(real_len);
            _recv_status = HTTP_RECV_OVER;
            return true;
        }
        //  3.2 缓冲区中数据，无法满足当前正文的需要，数据不足，取出数据，然后等待新数据到来
        _req_message._body.append(buf->ReadPosition(), buf->ReadbleSize());
        buf->MoveReadOffest(buf->ReadbleSize());
        return true;
    }

public:
    HttpContext() : _resp_status(200), _recv_status(HTTP_RECV_LINE)
    {
    }

    void Reset()
    {
        _recv_status = HTTP_RECV_LINE;
        _req_message.Reset();
        _resp_status = 200;
    }

    int HttpRespStatus() // 响应状态码
    {
        return _resp_status;
    }
    HttpRecvStatus RecvStatus() // 接收状态
    {
        return _recv_status;
    }
    HttpRequest &Request()
    {
        return _req_message;
    }
    void RecvHttpRequest(Buffer *buffer) // 接收并解析http请求
    {
        switch (_recv_status)
        {
        case HTTP_RECV_LINE:
            RecvHttpLine(buffer);
        case HTTP_RECV_HEAD:
            RecvHttpHead(buffer);
        case HTTP_RECV_BODY:
            RecvHttpBody(buffer);
        }
        return;
    }
};
using Handler = std::function<void(HttpRequest &, HttpResponse *)>;
using Handlers = std::vector<std::pair<std::regex, Handler>>;
class HttpServer
{
private:
    Handlers _get_routine;
    Handlers _post_routine;
    Handlers _put_routine;
    Handlers _delete_routine;
    std::string _root_dir;
    TcpServer _server;

private:
    void WriteResponse(const PtrConnection &_conn, HttpRequest &req, HttpResponse &rsp)
    {
        if (req.Close() == true)
        {
            rsp.SetHeader("Connection", "close");
        }
        else
        {
            rsp.SetHeader("Connection", "keep-alive");
        }
        if (rsp._body.empty() == false && rsp.HasHeader("Content-Length") == false)
        {
            rsp.SetHeader("Content-Length", std::to_string(rsp._body.size()));
        }
        if (rsp._body.empty() == false && rsp.HasHeader("Content-Type") == false)
        {
            rsp.SetHeader("Content-Type", "application/octet-stream");
        }
        if (rsp._redict_flag == true)
        {
            rsp.SetHeader("Location", rsp._redict_url);
        }
        // 2. 将rsp中的要素，按照http协议格式进行组织
        std::stringstream rsp_str;
        rsp_str << req._version << " " << std::to_string(rsp._status) << " " << Util::StatuDescribe(rsp._status) << "\r\n";
        for (auto &head : rsp._headers)
        {
            rsp_str << head.first << ": " << head.second << "\r\n";
        }
        rsp_str << "\r\n";
        rsp_str << rsp._body;
        // 3. 发送数据
        _conn->Send((char *)rsp_str.str().c_str(), rsp_str.str().size());
    }

    bool IsStaticSource(const HttpRequest &req)
    {
        // 1. 必须设置了静态资源根目录
        if (_root_dir.empty())
        {
            return false;
        }
        // 2. 请求方法，必须是GET / HEAD请求方法
        if (req._method != "GET" && req._method != "HEAD")
        {
            return false;
        }
        // 3. 请求的资源路径必须是一个合法路径
        if (Util::IsValid(req._path) == false)
        {
            return false;
        }
        // 4. 请求的资源必须存在,且是一个普通文件
        //    有一种请求比较特殊 -- 目录：/, /image/， 这种情况给后边默认追加一个 index.html
        // index.html    /image/a.png
        // 不要忘了前缀的相对根目录,也就是将请求路径转换为实际存在的路径  /image/a.png  ->   ./wwwroot/image/a.png
        std::string req_path = _root_dir + req._path; // 为了避免直接修改请求的资源路径，因此定义一个临时对象
        if (req._path.back() == '/')
        {
            req_path += "index.html";
        }
        if (Util::IsRegular(req_path) == false)
        {
            return false;
        }
        return true;
    }

    bool StaticSource(const HttpRequest &req, HttpResponse *rsp)
    {
        std::string req_path = _root_dir + req._path;
        if (req._path.back() == '/')
        {
            req_path += "index.html";
        }
        bool ret = Util::ReadFile(req_path, &rsp->_body);
        if (ret == false)
        {
            return false;
        }
        std::string mime = Util::ExMime(req_path);
        rsp->SetHeader("Content-Type", mime);
        return true;
    }
    void Dispatch(HttpRequest &req, HttpResponse *rsp, Handlers &_handlers)
    {
        for (auto &handler : _handlers)
        {
            const std::regex &re = handler.first;
            const Handler functor = handler.second;
            bool ret = std::regex_match(req._path, req._match, re);
            if (ret == false)
            {
                continue;
            }
            return functor(req, rsp); // 传入请求信息，和空的rsp，执行处理函数
        }
        rsp->_status = 404;
    }
    void Routine(HttpRequest &req, HttpResponse *rsp)
    {
        // 1. 对请求进行分辨，是一个静态资源请求，还是一个功能性请求
        //    静态资源请求，则进行静态资源的处理
        //    功能性请求，则需要通过几个请求路由表来确定是否有处理函数
        //    既不是静态资源请求，也没有设置对应的功能性请求处理函数，就返回405
        if (IsStaticSource(req) == true)
        {
            // 是一个静态资源请求, 则进行静态资源请求的处理
            StaticSource(req, rsp);
            return;
        }
        if (req._method == "GET" || req._method == "HEAD")
        {
            return Dispatch(req, rsp, _get_routine);
        }
        else if (req._method == "POST")
        {
            return Dispatch(req, rsp, _post_routine);
        }
        else if (req._method == "PUT")
        {
            return Dispatch(req, rsp, _put_routine);
        }
        else if (req._method == "DELETE")
        {
            return Dispatch(req, rsp, _delete_routine);
        }
        rsp->_status = 405; // Method Not Allowed
        return;
    }
    void OnConnected(const PtrConnection &conn)
    {
        conn->SetContext(HttpContext());
    } // 设置上下文

    void ErrorHandler(const HttpRequest &_req, HttpResponse *_rsp)
    {
        std::string body;
        body += "<html>";
        body += "<head>";
        body += "<meta http-equiv='Content-Type' content='text/html;charset=utf-8'>";
        body += "</head>";
        body += "<body>";
        body += "<h1>";
        body += std::to_string(_rsp->_status);
        body += " ";
        body += Util::StatuDescribe(_rsp->_status);
        body += "</h1>";
        body += "</body>";
        body += "</html>";

        _rsp->SetContent(body);
    }

    void OnMessage(const PtrConnection &conn, Buffer *buffer)
    {
        while (buffer->ReadbleSize() > 0)
        {
            HttpContext *_context = std::any_cast<HttpContext>(conn->GetContext());
            _context->RecvHttpRequest(buffer);
            if (_context->HttpRespStatus() >= 400)
            {
                HttpRequest _req;
                HttpResponse _rsp(_context->HttpRespStatus());
                ErrorHandler(_req, &_rsp);
                WriteResponse(conn, _req, _rsp);
                _context->Reset();
                buffer->MoveReadOffest(buffer->ReadbleSize());
                conn->ShutDown();
                return;
            }

            if (_context->RecvStatus() != HTTP_RECV_OVER)
            {
                return;
            }

            HttpRequest &req = _context->Request();
            HttpResponse _rsp;

            Routine(req, &_rsp);
            WriteResponse(conn, req, _rsp);
            _context->Reset();

            if (_rsp.Close())
            {
                conn->ShutDown();
            }
        }
        return;
    }

public:
    HttpServer(int port,int timeout = 30):_server(port)
    {
        _server.EnableInactiveRelease(timeout);
        _server.SetConnectionCallBack(std::bind(&HttpServer::OnConnected,this,std::placeholders::_1));
        _server.SetMessageCallBack(std::bind(&HttpServer::OnMessage,this,std::placeholders::_1,std::placeholders::_2));

    }
    void SetRootDir(const std::string& path)
    {
        _root_dir = path;
    }
    void AddGetRoutine(const std::string &_key, const Handler &_value)
    {
        _get_routine.push_back(std::make_pair(std::regex(_key),_value));
    }
    void AddPostRoutine(const std::string &_key, const Handler &_value)
    {
        _post_routine.push_back(std::make_pair(std::regex(_key),_value));

    }
    void AddDeleteRoutine(const std::string &_key, const Handler &_value)
    {
        _delete_routine.push_back(std::make_pair(std::regex(_key),_value));
        
    }
    void AddPutRoutine(const std::string &_key, const Handler &_value)
    {
        _put_routine.push_back(std::make_pair(std::regex(_key),_value));

    }
    void SetThreadsCounts(int count)
    {
        _server.SetThreadsCounts(count);
    }
    void Listen()
    {
        _server.Start();
    }
};
